#!/usr/bin/env python


#       Copyright 2008 Umang Vipul <umangvipul@gmail.com> , eon <srivar@gmail.com>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

#       Send bug reports and contributions to the website:
#       http://code.google.com/p/lanser


###### to do list for next version ######
 ## bug in the watched folder/files
 ## option to destroy index and loadable in the secondary store
 ## to make the iprange configurable
 ## to add set opertions on the searchs str such as intersection ,union
 ## to streamline the code
 ## to use suffix trees[ so that cold returns coldplay]
######            ######

import pygtk
pygtk.require('2.0')
import gtk, gobject
import socket,threading,pickle,os,copy,sys,os.path
from ValidatedEntry import *



# Global Variables ----------------------------------------------------------------------------------------------------------

indexlist=[]                                        # list of directories and files to be indexed
setlist=set()                                       # a set of dir's already indexed for fast membership testing
indexnum=0                                          # the index num ( for indexlist) uptill which indexing has been done 

commonwords=['the','of','to','and','a','an','in','is','it','that','for','on','are','as','i','they'] 
                                                    # list of common words i ignore while indexing

result=[]                                           # final result of the search query (should be a local variable !!)


trielock=threading.Lock()                           # lock to manage sync of the trie
resultlock=threading.Lock()                         # lock to manage sync of the result 


shost=socket.gethostbyname(socket.gethostname())    # ur ip goes here
sport=65494                         


servhost=[shost]                                    # list consisting of all the servers (:-( , hand coded), have to develop
                                                    # a mechanism , to make it configurable from the front end
servport=65494                                      # 2^16-42


# Useful functions ---------------------------------------------------------------------------------------------------------



def tokenizer(strname):
    """ forms tokens of the file name and returns them in a list """
    token=[]
    s=strname.split()
    for i in s:
        tok=i.split('-')
        for j in tok:
            token.append(j)
    return token

def inserter(strname,path):
    """ Inserts the file name into the trie """
    s=tokenizer(strname)
    for i in s:
        if i==s[len(s)-1]:
            if (not i.split('.')[0].isdigit()) and not iscommon(i.split('.')[0].lower()):
                trie.insert(i.split('.')[0].lower(),path)
        else:
            if i.isalnum() and (not i.isdigit()) and not iscommon(i.lower()):
                trie.insert(i.lower(),path)
                

def iscommon(strname):
    """ Checks whether the token is one of the common words returns true incase of a match else false """
    for i in commonwords:
        if i==strname:
            return True
        else:
            return False
        

def insearchin(strlst):
    """ Checks incoming search query in the trie and stores the result[the paths] in a list and returns it """
    paths=[]
    for i in strlst:
        temp=[]
        a=trie.search(key(i.lower()))
        if a is not None:
            if paths==[] :
                for k in a.path:
                    if k is not None:
                        temp.append(k)
            else:
                for n in paths:
                    for j in a.path:
                        if n==j:
                            temp.append(n)
        paths=copy.copy(temp)
    return paths



    
def outsearchin_gen(strlst):
    """ gen obj for outsearchin"""
    outsearchin_obj=outsearchin(strlst)
    gobject.idle_add(outsearchin_obj.next)
    #return outsearchin_obj.next()

def Dec2Bin(n):
    """ decimal to binary string """
    bStr = ''
    if n < 0:  
        raise ValueError, "must be a positive integer"
    if n == 0: 
        return '0'
    while n > 0:
        bStr = str(n % 2) + bStr
        n = n >> 1
    return bStr

def padbits(bStr):
    """ pads extra bits to make it a 32 bit key """
    while len(bStr)<32:
        bStr='0'+bStr
    return bStr

def encode(string):
    """ hash function , refer dragon book """
    if string==None:
        return 0
    bits=4*8
    bit=long((bits*3)/4)
    b=long(bits/8)
    bi=(0xFFFFFFFF)<<(bits-b)
    hash=0
    temp=0
    for i in range(len(string)):
        hash=(hash<<b)+ord(string[i])
        temp=hash&bi
        if temp!=0:
            hash=((hash^(temp>>bit))&(~bi))
    return (hash&0x7FFFFFFF)

def key(string):
    """ final 32bit key """
    return padbits(Dec2Bin(encode(string)))

def digit(key,num):
    """ returns the digit at num position in the key """
    return ord(key[len(key)-1-num])-ord('0')

#Trie implementation ---------------------------------------------------------------------------------------------------

# A standard implementation of the patricia  

class KNode:
    left,right,data,digit=None,None,0,0
    def __init__(self,data,path,digit):
        """ initializes the data members """
        self.left=None
        self.right=None
        self.data=data
        self.path=[]
        self.path.append(path)
        self.digit=digit

class Trie:
    def __init__(self):
        self.root=KNode(None,None,-1)
        self.root.left=self.root
        self.root.right=self.root
        
    def addNode(self,data,path,digit):
        return KNode(data,path,digit)
    
    def searchR(self,node,keystr,dgit):
        """ search for a node """
        if node.digit<=dgit:
            return node
        if digit(keystr,node.digit)==0:
            return self.searchR(node.left,keystr,node.digit)
        else:
            return self.searchR(node.right,keystr,node.digit)
        
    def search(self,keystr):
        """ uses searchR and does final comparision """
        tempnode=self.searchR(self.root.left,keystr,-1)
        if keystr==key(tempnode.data):
             return tempnode
        else:
            None
                     
    def insertR(self,node,data,path,dgit,parnode):
        """ insert a node """
        keystr=key(data)
        if (node.digit>=dgit)or(node.digit<=parnode.digit):
            tmpnode=self.addNode(data,path,dgit)
            if digit(keystr,tmpnode.digit)==1:
                tmpnode.left=node
                tmpnode.right=tmpnode
            else:
                tmpnode.left=tmpnode
                tmpnode.right=node
            return tmpnode
        if digit(keystr,node.digit)==0:
            node.left=self.insertR(node.left,data,path,dgit,node)
        else:
            node.right=self.insertR(node.right,data,path,dgit,node)
        return node
            
    def insert(self,data,path):
        """ uses insertR """
        keystr=key(data)
        tmpnode=self.searchR(self.root.left,keystr,-1)
        nodestr=key(tmpnode.data)
        if keystr==nodestr:
            for i in tmpnode.path:
                if i==path:
                    return None
            tmpnode.path.append(path)
            return None
        dgit=0
        while(digit(keystr,dgit)==digit(nodestr,dgit)):
            dgit=dgit+1
        self.root.left=self.insertR(self.root.left,data,path,dgit,self.root)

# GUI part -----------------------------------------------------------------------------------------------------------------

# needs some changes

def pbar_do(pbobj):
        pbobj.progressbar.pulse()
        return True
    
class lanserGUI(): 

    def autogen_ip(self):
       for i in xrange(int(self.iprange3.get_text()),int(self.iprange7.get_text())+1):
            for j in xrange(256):
                if(i==int(self.iprange3.get_text()) and j<int(self.iprange4.get_text())):
                    pass
                elif(i!=int(self.iprange7.get_text())):
                    servhost.append('172.16'+'.'+str(i)+'.'+str(j))
                else:
                    servhost.append('172.16'+'.'+str(i)+'.'+str(j))
                    if(j==int(self.iprange8.get_text())):
                        break
                
                    
            
    
    def ip_compare(self):
        if int(self.iprange7.get_text()) > int(self.iprange3.get_text()):
            return True
        elif int(self.iprange7.get_text()) == int(self.iprange3.get_text()):
            if int(self.iprange8.get_text()) > int(self.iprange4.get_text()):
                return True
            else:
                return False
        else:
            return False
    
    #the callback function for checking valid IP address
    def checkIP(self, data = None):
        activate = False
        if self.radiorange.get_active():
            if (self.iprange1.isvalid() and self.iprange2.isvalid() and self.iprange3.isvalid() and self.iprange4.isvalid() and self.iprange5.isvalid() and self.iprange6.isvalid() and self.iprange7.isvalid() and self.iprange8.isvalid() and self.ip_compare() ):
                activate = True
        if self.radiosingle.get_active():
            if (self.ipsingle1.isvalid() and self.ipsingle2.isvalid() and self.ipsingle3.isvalid() and self.ipsingle4.isvalid()):
                activate = True
        self.btnAddServer.set_sensitive(activate)
        self.btnRemove.set_sensitive(activate)
    
    
    #returning True on delete-event doesn't exit the gtk-main loop
    def on_window_delete_event(self, widget, data=None):

        self.window.hide()
        self.visible = False
        return True
    
    #negate the visible state of the window
    def show_window(self, status_icon, data=None):
        if self.visible:
            self.window.hide()
            self.visible = False
            
        else:
            self.window.show()
            self.visible = True
            
    def tray_context_menu(self, status_icon, button, activate_time, data=None):
        self.tray_contextmenu.popup(None, None, None, button, activate_time)
               
    
    def on_tray_quit_item_activate(self, menuitem, data = None):
        self.statusicon.set_visible(False)
        sys.exit(0)
        
    def on_tray_showhide_item_activate(self, menuitem, data = None):
        if self.visible:
            self.window.hide()
            self.visible = False
            
        else:
            self.window.show()
            self.visible = True
        
    
    def on_quit_menu_item_activate(self, menuitem, data=None):
        self.statusicon.set_visible(False)
        sys.exit(0)
    
    
    def on_btnClose_clicked(self, widget, data=None):
        self.dialog1.hide()
        
    def on_addfile_menu_item_activate(self, menuitem, data=None):
        filenames = self.select_filename()
        for file in filenames:
            indexlist.append(file)
        self.status_bar.push(self.context_id,'Now click on build to start building the index')
        
    def on_addfolder_menu_item_activate(self, menuitem, data=None):
        foldername = self.select_folder()
        indexlist.append(foldername)
        self.status_bar.push(self.context_id,'Now click on build to start building the index')
        
    def on_servadd_menu_item_activate(self, menuitem, data=None):
        self.textbuffer3.set_text('')     
        for i in servhost:
            self.textbuffer3.insert_at_cursor(i)
            self.textbuffer3.insert_at_cursor('\n')
        
        self.iprange1.set_text('')                
        self.iprange2.set_text('')
        self.iprange3.set_text('')
        self.iprange4.set_text('')
        self.iprange5.set_text('')
        self.iprange6.set_text('')
        self.iprange7.set_text('')
        self.iprange8.set_text('')
        
        self.ipsingle1.set_text('')
        self.ipsingle2.set_text('')
        self.ipsingle3.set_text('')
        self.ipsingle4.set_text('')
        
        self.servadd.show()
        
    
            
    
    def on_btnAddServer_clicked(self, widget, data=None):
        if self.radiosingle.get_active():
            servhost.append(self.ipsingle1.get_text()+'.'+self.ipsingle2.get_text()+'.'+self.ipsingle3.get_text()+'.'+self.ipsingle4.get_text())
        
        else:
            self.autogen_ip()                   #generate ip here and append  
            
        self.textbuffer3.set_text('')     
        for i in servhost:
            self.textbuffer3.insert_at_cursor(i + '\n')
            
            
    def on_btnRemove_clicked(self, widget, data=None):
        if self.radiosingle.get_active():
            servhost.remove(self.ipsingle1.get_text()+'.'+self.ipsingle2.get_text()+'.'+self.ipsingle3.get_text()+'.'+self.ipsingle4.get_text())

        else:                   #generate ip here and remove    
            pass
            
        self.textbuffer3.set_text('')     
        for i in servhost:
            self.textbuffer3.insert_at_cursor(i + '\n')
            
       
    def on_btnbuildIndex_clicked(self, widget, data=None):
        
        buildIndex_obj=self.buildIndex()
        gobject.idle_add(buildIndex_obj.next)
        

        
    def on_btnsearchIndex_clicked(self, widget, data=None):
        
        searchIndex_obj=self.searchIndex()
        gobject.idle_add(searchIndex_obj.next)

    def on_searchbar_activate(self, widget, data=None):
        searchIndex_obj=self.searchIndex()
        gobject.idle_add(searchIndex_obj.next)

    
    def on_btnCloseS_clicked(self, widget, data=None):
        self.servadd.hide()
        
    def on_radiosingle_toggled(self, widget, data = None):
        self.singlehbox.set_sensitive(self.radiosingle.get_active())
        self.checkIP(None)
        
    def on_radiorange_toggled(self, widget, data = None):
        self.rangehbox.set_sensitive(self.radiorange.get_active())
        self.checkIP(None)
        
    def on_about_menu_item_activate(self, menuitem, data=None):
    
        if self.about_dialog: 
            self.about_dialog.present()
            return
        
        authors = [
        "eon <srivar@gmail.com>",    
        "Umang Vipul <umangvipul@gmail.com> gtk GUI"
        ]
        
        license = """        You may modify and redistribute the program under the 
        terms of the GPL (version 2 or later).  A copy of the GPL is 
        contained in the 'COPYING' file distributed with lanser.  
        lanser is copyrighted by its contributors. We provide no warranty 
        for this program.
    """
        artists = ["Dry Icons: http://dryicons.com", "from \"Coquette Icons\" set 'promotion'"]

        about_dialog = gtk.AboutDialog()
        about_dialog.set_transient_for(self.window)
        about_dialog.set_destroy_with_parent(True)
        about_dialog.set_name("Lanser")
        about_dialog.set_version("0.01")
        about_dialog.set_copyright("Copyright \xc2\xa9 2008 Umang Vipaul [GUI] , eon [the rest]") 
        about_dialog.set_website("http://code.google.com/p/lanser/")
        about_dialog.set_comments("An attempt to make a search aid for the college lan.")
        about_dialog.set_authors(authors)
        about_dialog.set_license(license)
        about_dialog.set_artists(artists)

        
        def close(dialog, response, lanser):
            lanser.about_dialog = None
            dialog.destroy()
            
        def delete_event(dialog, event, lanser):
            lanser.about_dialog = None
            return True
                    
        about_dialog.connect("response", close, self)
        about_dialog.connect("delete-event", delete_event, self)
        
        self.about_dialog = about_dialog
        about_dialog.show()
        
    def on_view_menu_item_activate(self, menuitem, data=None):
        self.textbuffer2.set_text('')     
        for i in indexlist:
            self.textbuffer2.insert_at_cursor(i )
            self.textbuffer2.insert_at_cursor('\n')
            

        self.dialog1.show()
        
    def on_searchbar_changed(self, widget, data=None):
        if self.SEARCHING and (self.searchBar.get_text()!=''):
            self.btnSearchIndex.set_sensitive(True)
        else:
            self.btnSearchIndex.set_sensitive(False)
            
        
    
        
    def select_filename(self):
        
        filename = None
        chooser = gtk.FileChooserDialog("Select File...", self.window,
                                        gtk.FILE_CHOOSER_ACTION_OPEN,
                                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, 
                                         gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        chooser.set_select_multiple(True)
        response = chooser.run()
        if response == gtk.RESPONSE_OK: 
            filename = chooser.get_filenames()
            self.hbox.show()
        chooser.destroy()
        
        return filename
    
    def select_folder(self):
        foldername = None
        chooser = gtk.FileChooserDialog("Select Folder...", self.window,
                                        gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, 
                                         gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        
        response = chooser.run()
        if response == gtk.RESPONSE_OK: 
            foldername = chooser.get_filename()
            self.hbox.show()
        chooser.destroy()
        return foldername
        
    def error_message(self, message):
    
        # log to terminal window
        print message
        
        # create an error message dialog and display modally to the user
        dialog = gtk.MessageDialog(None,
                                   gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                                   gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, message)
        
        dialog.run()
        dialog.destroy()
        
    def __init__(self):
        self.filemane = None
        self.foldername = None
        self.about_dialog = None
        
        self.SEARCHING = False
                
        location = os.path.dirname(os.path.abspath(__file__))
            
        # use GtkBuilder to build our interface from the XML file 
        try:
            builder = gtk.Builder()
            builder.add_from_file(os.path.join(location,"interface.xml")) 
                        
        except:
            self.error_message("Failed to load UI XML file")
            sys.exit(1)
        
        
        builder.connect_signals(self)
        
        
        
        # get the widgets from interface.xml which will be referenced in callbacks
        self.window = builder.get_object("window")
        self.visible = True
        self.status_bar = builder.get_object("statusbar")
        self.textView = builder.get_object("textView")
        self.textbuffer = self.textView.get_buffer()
        self.searchBar = builder.get_object("searchbar")
        self.hbox = builder.get_object("hbox1")
        self.btnSearchIndex = builder.get_object("btnsearchIndex")
        
        
        self.progressbar = builder.get_object("progressbar")
        
        self.context_id = self.status_bar.get_context_id("Status Display")
        self.status_bar.push(self.context_id,'Add file(s)/folder(s) for watching')
        
        #objects of watch content dialog
        self.displaylist = builder.get_object("IndexlistContents")
        self.dialog1= builder.get_object("dialog1")
        self.textbuffer2 = self.displaylist.get_buffer()
        
        #objects of addserver dialog
        self.servadd = builder.get_object("serverAddDialog")
        self.servList = builder.get_object("serverList")
        self.textbuffer3 = self.servList.get_buffer()
        self.btnAddServer = builder.get_object("btnAddServer")
        self.btnRemove = builder.get_object("btnRemove")
        #the hboxes and radio buttons in add server dialog
        self.rangehbox = builder.get_object("rangehbox")
        self.singlehbox = builder.get_object("singlehbox")
        self.radiorange = builder.get_object("radiorange")
        self.radiosingle = builder.get_object("radiosingle")
        
        #tray icon context menu
        self.tray_contextmenu = builder.get_object("tray_contextmenu")
        
        #ValidatedEntry objects and labels. Not available in glade hence this mess
        #ugly. very ugly. fugly.
        USE_BACKGROUND_COLOR = True

        self.iprange1 = ValidatedEntry(bounded(v_int, int, 172, 172),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange1.set_max_length(3)
        self.iprange1.set_width_chars(3)
        self.iprange1.connect('changed', self.checkIP)        
        self.dot1 = gtk.Label(".")
        
        self.iprange2 = ValidatedEntry(bounded(v_int, int, 16, 16),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange2.set_max_length(3)
        self.iprange2.set_width_chars(3)
        self.iprange2.connect('changed', self.checkIP)
        self.dot2 = gtk.Label(".")
        
        self.iprange3 = ValidatedEntry(bounded(v_int, int, 50, 60),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange3.set_max_length(3)
        self.iprange3.set_width_chars(3)
        self.iprange3.connect('changed', self.checkIP)
        self.dot3 = gtk.Label(".")
        
        self.iprange4 = ValidatedEntry(bounded(v_int, int, 0, 255),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange4.set_max_length(3)
        self.iprange4.set_width_chars(3)
        self.iprange4.connect('changed', self.checkIP)
        
        self.to = gtk.Label("to")
        
        self.iprange5 = ValidatedEntry(bounded(v_int, int, 172, 172),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange5.set_max_length(3)
        self.iprange5.set_width_chars(3)
        self.iprange5.connect('changed', self.checkIP)
        self.dot4 = gtk.Label(".")
        
        self.iprange6 = ValidatedEntry(bounded(v_int, int, 16, 16),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange6.set_max_length(3)
        self.iprange6.set_width_chars(3)
        self.iprange6.connect('changed', self.checkIP)
        self.dot5 = gtk.Label(".")
        
        self.iprange7 = ValidatedEntry(bounded(v_int, int, 50, 60),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange7.set_max_length(3)
        self.iprange7.set_width_chars(3)
        self.iprange7.connect('changed', self.checkIP)
        self.dot6 = gtk.Label(".")
        
        self.iprange8 = ValidatedEntry(bounded(v_int, int, 0, 255),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.iprange8.set_max_length(3)
        self.iprange8.set_width_chars(3)
        self.iprange8.connect('changed', self.checkIP)
        
        self.rangehbox.pack_start(self.iprange1, False, False, 2)
        self.rangehbox.pack_start(self.dot1, False, False, 0)

        self.rangehbox.pack_start(self.iprange2, False, False, 2)
        self.rangehbox.pack_start(self.dot2, False, False, 0)

        self.rangehbox.pack_start(self.iprange3, False, False, 2)
        self.rangehbox.pack_start(self.dot3, False, False, 0)
        
        self.rangehbox.pack_start(self.iprange4, False, False, 2)
        
        self.rangehbox.pack_start(self.to, False, False, 2)
        
        self.rangehbox.pack_start(self.iprange5, False, False, 2)
        self.rangehbox.pack_start(self.dot4, False, False, 0)

        self.rangehbox.pack_start(self.iprange6, False, False, 2)
        self.rangehbox.pack_start(self.dot5, False, False, 0)

        self.rangehbox.pack_start(self.iprange7, False, False, 2)
        self.rangehbox.pack_start(self.dot6, False, False, 0)
        
        self.rangehbox.pack_start(self.iprange8, False, False, 2)

        
        self.ipsingle1 = ValidatedEntry(bounded(v_int, int, 0, 255),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.ipsingle1.set_max_length(3)
        self.ipsingle1.set_width_chars(3)
        self.ipsingle1.connect('changed', self.checkIP)
        self.dot7 = gtk.Label(".")
        
        self.ipsingle2 = ValidatedEntry(bounded(v_int, int, 0, 255),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.ipsingle2.set_max_length(3)
        self.ipsingle2.set_width_chars(3)
        self.ipsingle2.connect('changed', self.checkIP)
        self.dot8 = gtk.Label(".")
        
        self.ipsingle3 = ValidatedEntry(bounded(v_int, int, 0, 255),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.ipsingle3.set_max_length(3)
        self.ipsingle3.set_width_chars(3)
        self.ipsingle2.connect('changed', self.checkIP)
        self.dot9 = gtk.Label(".")
        
        self.ipsingle4 = ValidatedEntry(bounded(v_int, int, 0, 255),max=3, use_bg=USE_BACKGROUND_COLOR)
        #self.ipsingle4.set_max_length(3)
        self.ipsingle4.set_width_chars(3)
        self.ipsingle4.connect('changed', self.checkIP)
        
        self.singlehbox.pack_start(self.ipsingle1, False, False, 2)
        self.singlehbox.pack_start(self.dot7, False, False, 0)
        
        self.singlehbox.pack_start(self.ipsingle2, False, False, 2)
        self.singlehbox.pack_start(self.dot8, False, False, 0)
        
        self.singlehbox.pack_start(self.ipsingle3, False, False, 2)
        self.singlehbox.pack_start(self.dot9, False, False, 0)
        
        self.singlehbox.pack_start(self.ipsingle4, False, False, 2)
        
        self.rangehbox.show_all()
        self.singlehbox.show_all()       
        #------------------------------------------------------------------#
        
        
        #default icon. defualt value for all the icons in the program
        gtk.window_set_default_icon_from_file(os.path.join(location,"lanser.png"))
        
        #tray icon
        self.statusicon = gtk.StatusIcon()
        self.statusicon.set_from_file(os.path.join(location,"lanser.ico"))
        self.statusicon.set_visible(True)
        self.statusicon.set_tooltip("lanser")
        self.statusicon.connect("activate", self.show_window, None)
        self.statusicon.connect("popup-menu",self.tray_context_menu, None)
        

        
        
        
            
    def buildIndex(self):
        """ really sad solution """
        self.SEARCHING = True 
        self.searchBar.set_sensitive(True)
        self.status_bar.push(self.context_id,'Building Index')
        self.progressbar.show()
        self.searchBar.set_sensitive(False)
        # Add a timer callback to update the value of the progress bar
        self.timer = gobject.timeout_add (100, pbar_do, self)
        global indexnum
        trav=indexlist[indexnum:]
        for i in trav:
            if i not in setlist:
                if os.path.isdir(unicode(i,'utf-8','replace')):
                    #crawler_gen(unicode(i,'utf-8','replace'))
                    dfname=(unicode(i,'utf-8','replace'))
                    for root,dirs,files in os.walk(dfname):
                        for i in dirs:
                            if i not in setlist:
                                setlist.add(os.path.join(root,i))
                            yield True
                        for i in files:
                            if not os.path.islink(os.path.join(root,i)):
                                inserter(i,os.path.join(root,i))
                            yield True
                else:
                    inserter(unicode(os.path.split(i)[1],'utf-8','replace'),unicode(i,'utf-8','replace'))
        #self.status_bar.push(self.context_id,'Indexing complete')
        indexnum=len(indexlist)
        self.timer = None
        self.progressbar.hide()
        self.searchBar.set_sensitive(True)
        self.status_bar.push(self.context_id,'Indexing complete')
        yield False 
        
    def searchIndex(self):
        self.status_bar.push(self.context_id,'Searching Index')
        self.progressbar.show()
        # Add a timer callback to update the value of the progress bar
        self.timer = gobject.timeout_add (100, pbar_do, self)
        global result
        #paths_flag=True
        #outsearchin_gen(pickle.dumps(unicode(self.searchBar.get_text(),'utf-8','replace').split()))
        strlst=pickle.dumps(unicode(self.searchBar.get_text(),'utf-8','replace').split())
        paths=[]
        threadslst=[]
        for i in range(len(servhost)):
            th=Clnt(i,strlst)
            threadslst.append(th)
            th.start()
            yield True
        for i in threadslst:
            i.join()
            yield True
        for i in result:
            for j in i:
                paths.append(j)
            yield True
        result=[]
        #paths_flag=False
        #yield False
        if paths==[]:
            self.textbuffer.set_text('No items found')
        else:
            self.textbuffer.set_text('')
            for i in paths:
                ##print i
                self.textbuffer.insert_at_cursor(i+'\n')
        self.timer = None
        self.progressbar.hide()
        #self.status_bar.push(self.context_id,'Indexing complete')
        self.status_bar.push(self.context_id,'Search complete')
        yield False

        
# Networking part ----------------------------------------------------------------------------------------------------------

# Server part --------------------------------------------------------

# The main thread , listens for connections and spawns a thread for each incoming request

class Serve(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        servsock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        servsock.bind((shost,sport))
        servsock.listen(5)
        while 1:
            conn,addr=servsock.accept()
            Servers(conn,addr).start()
        servsock.close()

# Threads for each connection request,each thread recieves the searchstr , searches the index and returns the result

class Servers(threading.Thread):
    def __init__(self,conn,addr):
        self.conn=conn
        self.addr=addr
        threading.Thread.__init__(self)

    def run(self):
        searchstr=''
        global trielock
        ch=self.conn.recv(4096)
        while ch:
            searchstr=searchstr+ch
            ch=self.conn.recv(4096)
        trielock.acquire()
        buf=pickle.dumps(insearchin(pickle.loads(searchstr)))
        trielock.release()
        totalsent=0
        while totalsent<len(buf):
            sent=self.conn.send(buf[totalsent:])
            if sent==0:
                raise RuntimeError,"socket connection broken"
            totalsent=totalsent+sent
        self.conn.close()

# Client part --------------------------------------------------------

# Each thread forms a connection with a server , and recieves the result of the search query

class Clnt(threading.Thread):
    def __init__(self,num,searchstr):
        threading.Thread.__init__(self)
        self.searchstr=searchstr
        self.num=num

    def run(self):
        global servhost,servport,resultlock,result
        resul=''
        try:
            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        except socket.error, msg:
            s = None
        try:
            s.connect((servhost[self.num],servport))
        except socket.error, msg:
            s.close()
            s = None
        if s is not None:
            totalsent=0
            while totalsent<len(self.searchstr):
                sent=s.send(self.searchstr[totalsent:])
                if sent==0:
                    raise RuntimeError,"socket connection broken"
                totalsent=totalsent+sent
            s.shutdown(socket.SHUT_WR)
            ch=s.recv(4096)
            while (ch):
                resul=resul+ch
                ch=s.recv(4096)
            if pickle.loads(resul) != []:
                resultlock.acquire()
                re=pickle.loads(resul)
                re.insert(0,servhost[self.num])
                result.append(re)
                resultlock.release()
            s.close() 

if __name__ == "__main__":
    trie=Trie()
    Serve().start()
    app = lanserGUI()
    gtk.main()
    sys.exit(0)
